package com.yunban.project.api.text_check.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.difflib.DiffUtils;
import com.github.difflib.patch.AbstractDelta;
import com.github.difflib.patch.Chunk;
import com.github.difflib.patch.Patch;
import com.google.common.base.Splitter;
import com.yunban.project.api.text_check.domain.*;
import com.yunban.project.api.text_check.dto.CorrectTaskResp;
import com.yunban.project.api.text_check.dto.CorrectionReq;
import com.yunban.project.api.text_check.enums.CorrectState;
import com.yunban.project.api.text_check.enums.CorrectionModel;
import com.yunban.project.api.text_check.mapper.TextCorrectTaskMapper;
import com.yunban.project.api.text_check.service.*;
import com.yunban.project.api.text_check.utils.CorrectUtils;
import com.yunban.project.api.text_check.utils.TextCorrectMatch;
import com.yunban.project.api.text_check.utils.TextCorrectionMatchResp;
import com.yunban.project.api.text_check.vo.CorrectTaskDetailsResp;
import com.yunban.project.api.text_check.vo.CreateCorrectTaskResp;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.base.common.exception.BusinessException;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author: lijiajun
 * @date: 2024-11-22
 * @version: 1.0
 */
@Slf4j
@Service
public class CorrectionFactory {

    private final Map<CorrectionModel, CorrectionService> strategyMap;

    @Resource
    private CorrectionConfigService correctionConfigService;

    @Resource
    private CorrectionDictService correctionDictService;

    @Resource
    private TextCorrectTaskMapper textCorrectTaskMapper;

    @Resource
    private CorrectTaskDetailsService correctTaskDetailsService;

    @Resource
    private ThreadConfigService threadConfigService;

    @Resource
    private UserCorrectionCharLimitService userCorrectionCharLimitService;

    @Autowired
    public CorrectionFactory(@Qualifier("xunFeiCorrectionService") XunFeiCorrectionServiceImpl xunFeiCorrectionService, @Qualifier("localCorrectionService") LocalCorrectionServiceImpl localCorrectionService, @Qualifier("baiduAiCorrectionService") BaiduAiCorrectionService baiduAiCorrectionService, @Qualifier("gradioAiCorrectionService") GradioAiCorrectionService gradioAiCorrectionService, @Qualifier("cozeAiCorrectionService") CozeAiCorrectionService cozeAiCorrectionService, @Qualifier("jiaoDuiCorrectionService") IJiaoDuiCorrectionServiceImpl jiaoDuiCorrectionService, @Qualifier("deepSeekCorrectionService") DeepSeekCorrectionService deepseekCorrectionService, @Qualifier("deepSeekApplicationCorrectionService") DeepSeekApplicationCorrectionService deepSeekApplicationCorrectionService, @Qualifier("aliyunCorrectionService") AliyunCorrectionService aliyunCorrectionService, @Qualifier("huoShanCorrectionService") HuoShanCorrectionService huoShanCorrectionService, @Qualifier("hunYuanApplicationCorrectionService") HunYuanApplicationCorrectionService hunYuanApplicationCorrectionService, @Qualifier("deepSeekGFService") DeepSeekGFService deepSeekGFService) {
        this.strategyMap = new HashMap<>(6);
        strategyMap.put(CorrectionModel.XUNFEI_API, xunFeiCorrectionService);
        strategyMap.put(CorrectionModel.LOCAL, localCorrectionService);
        strategyMap.put(CorrectionModel.BAIDU_AI, baiduAiCorrectionService);
        strategyMap.put(CorrectionModel.GRADIO_AI, gradioAiCorrectionService);
        strategyMap.put(CorrectionModel.COZE, cozeAiCorrectionService);
        strategyMap.put(CorrectionModel.I_JIAO_DUI, jiaoDuiCorrectionService);
        strategyMap.put(CorrectionModel.DEEPSEEK, deepseekCorrectionService);
        strategyMap.put(CorrectionModel.DEEPSEEK_APP, deepSeekApplicationCorrectionService);
        strategyMap.put(CorrectionModel.TONG_YI, aliyunCorrectionService);
        strategyMap.put(CorrectionModel.HUO_SHAN, huoShanCorrectionService);
        strategyMap.put(CorrectionModel.HUN_YUAN, hunYuanApplicationCorrectionService);
        strategyMap.put(CorrectionModel.DEEPSEEK_GF, deepSeekGFService);
    }


    public static void main(String[] args) {
        String text = "你号  猜猜我是和谁？";
        List<CorrectUtils.TextSegment> textSegments = CorrectUtils.punctuateSplitTextV2(text);
        System.out.println(JSON.toJSONString(textSegments));
    }


    /**
     * 添加文本纠错任务
     *
     * @param text 文本
     * @return 任务ID
     */
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public CreateCorrectTaskResp createCorrectTask(String text, int sentencesPerSegment) {
        log.info("添加文本纠错任务:{}", text);
        TextCorrectTask correctTask = new TextCorrectTask();
        text = text.replaceAll(" ", "");
        text = text.replaceAll("\r", "");
        correctTask.setText(text);
        this.textCorrectTaskMapper.insert(correctTask);
        log.info("添加文本纠错任务成功:{}", correctTask.getText());
        String taskId = correctTask.getCorrectTaskId();
        // 添加任务详情
        // 对文本进行分句处理
        // 去除 text中的换行
        // TODO 2025-03-12 ljiajun 修改分割逻辑，如果结尾标点后有结尾引号，那么则按 结尾引号进行分割
        // TODO 2025-03-13 lijiajun 修改了分割逻辑，按照 sentencesPerSegment 进行长度分割，之前是一句一句分割，
        // punctuateSplitTextV2 是可以按照\n进行分割，一段一段的样式 执行速度不错
        List<CorrectUtils.TextSegment> segments = CorrectUtils.punctuateSplitTextV2(text);
//        List<CorrectUtils.TextSegment> segments = CorrectUtils.punctuateSplitTextV3(text, sentencesPerSegment);
        this.correctTaskDetailsService.batchSaveTask(taskId, segments);
        // 使用纠错字符数
        this.userCorrectionCharLimitService.useCount(SmartRequestUtil.getUserId(), text.length());
        CreateCorrectTaskResp resp = new CreateCorrectTaskResp();
        resp.setTaskId(taskId);
        int totalCount = 0;
        for (CorrectUtils.TextSegment segment : segments) {
            if (!segment.getText().equals("\n") && !segment.getText().equals("\n\n") && !segment.getText().equals("<br/>")) {
                totalCount++;
            }
        }
        resp.setTotalCount(totalCount);
        return resp;
    }


    public void correctionTask() {
        // 假如有需要进行解析的任务，那么则需要查询一下当前有没有空闲的线程，如果有的话则进行解析纠错
        Boolean hasAvailableThread = this.threadConfigService.checkCurrentThreadConfig();
        if (!hasAvailableThread) {
            log.debug("当前没有空闲的线程，无法进行文本纠错");
            return;
        }
        // 获取一下当前有没有待处理的任务
        CorrectTaskDetails unParsedTask = this.correctTaskDetailsService.getUnParsedTask();
        if (ObjectUtils.isEmpty(unParsedTask)) {
            log.debug("当前没有待处理的任务");
            return;
        } else {
            // 有任务、有线程，进行纠错，需要先锁一个线程
            log.info("当前有空闲的线程，开始进行文本纠错");
            if (!this.threadConfigService.useThread()) {
                log.debug("纠错任务线程占用失败，无法进行文本纠错");
                // TODO 2024-12-18 线程占用失败时，需要回滚解析任务状态, 否则就会丢失任务 (状态一直是解析中)
                unParsedTask.setState(CorrectState.UNKNOWN);
                this.correctTaskDetailsService.updateById(unParsedTask);
                return;
            }
        }

        // 开始纠错
        try {
            /*
             这个地方需要注意一下，因为 文本按照 某几个标点符号进行分割的，所以会出现 某一个标点符号是一句的情况，这个情况直接手动构建返回就好，不需要在进行解析了
             构建返回，写入具体任务记录中
             假如需要解析的文本是空串，那么则不需要进行解析
            */
            // 将unParsedTask.getSentence() 的空格替换为 ""
            String s = unParsedTask.getSentence().replaceAll(" ", "");
            // \r 改为 ""
            s = s.replaceAll("\r", "");
            unParsedTask.setSentence(s);
            if (StringUtils.hasText(s)) {
                List<TextCorrectionMatchResp> resp = buildSpecialSentenceCorrectResult(s);
                if (s.equals("<br/>")) {
                    unParsedTask.setResult(new ArrayList<>());
                } else if (!ObjectUtils.isEmpty(resp)) {
                    unParsedTask.setResult(resp);
                } else {
                    // 调用模型与第三方接口进行纠错业务
                    correction(unParsedTask);
                }
            }
            // 修改任务状态为已完成
            unParsedTask.setState(CorrectState.SUCCESS);
        } catch (Exception e) {
            // 失败的话，需要修改状态为失败
            unParsedTask.setState(CorrectState.FAIL);
            log.error("文本纠错定时任务异常", e);
            log.error("文本纠错定时任务异常：{}", e.getMessage());
        } finally {
            // 不管成功与失败都要释放线程
            this.threadConfigService.releaseThread();
            // 修改状态
            if (!this.correctTaskDetailsService.updateById(unParsedTask)) {
                log.error("修改任务状态为已完成失败:taskDetailsId:{}", unParsedTask.getId());
            }
            // 检查当前任务是否已经解析完了
            boolean finished = this.correctTaskDetailsService.checkTaskFinished(unParsedTask.getTaskId());
            if (finished) {
                // 修改任务状态为已完成
                this.textCorrectTaskMapper.finishTask(unParsedTask.getTaskId());
            }
        }
    }

    // 构建特殊句子纠错结果
    private List<TextCorrectionMatchResp> buildSpecialSentenceCorrectResult(String sentence) {
        List<String> strings = CorrectUtils.sentencePunctuateListV2();
        List<String> sentencePunctuates = new ArrayList<>(strings);
//        sentencePunctuates.add("<br/>");
        if (sentencePunctuates.contains(sentence)) {
            // 构建返回，写入具体任务记录中
            CorrectionConfig config = this.correctionConfigService.findByCode(CorrectionModel.LOCAL);
            TextCorrectionMatchResp resp = new TextCorrectionMatchResp(CorrectionModel.LOCAL, config.getName(), null, 0, 1, sentence, "", LocalDateTime.now(), null, 0, "三级");
            return List.of(resp);
        }
        return null;
    }

    void correction(CorrectTaskDetails task) {
        // 首先查询一下有没有正在进行的任务
        List<CorrectionConfig> configList = this.correctionConfigService.getEnabledConfigList();
        if (ObjectUtils.isEmpty(configList)) {
            throw new BusinessException("未配置文本纠错配置信息");
        }
        List<List<TextCorrectionMatchResp>> correctResults = new ArrayList<>();
        List<Long> localDictIds = new ArrayList<>();
        String taskId = task.getTaskId();
        // 获取用户ID
        configList.forEach(correctConfig -> {
            CorrectionModel code = correctConfig.getCode();
            CorrectionService correctService = strategyMap.get(code);
            if (ObjectUtils.isEmpty(correctService)) {
                log.error("未找到匹配的文本纠错策略，model:{}", code);
                throw new BusinessException("未找到匹配的文本纠错策略:" + code.getDesc());
            }
            // 如果 task.getSentence() 是<br/>结尾，那么则需要先去除掉再进行纠错
            if (task.getSentence().endsWith("<br/>")) {
                task.setSentence(task.getSentence().substring(0, task.getSentence().length() - 5));
            }
            log.info("源文本1：{}", task.getSentence());
            // TODO 2025-03-14 LIJIAJUN 替换敏感词 sourceText
            String sourceText = this.correctionDictService.sensitiveWordPlace(task.getSentence(), false);
            // TODO 2025-03-17 LIJIAJUN 如果是本地库配置，那么则跳过，因为事先使用本地库进行了一遍匹配
            log.info("源文本2：{}", sourceText);
            if (code.equals(CorrectionModel.LOCAL)) {
                return;
            }
            // TODO 2025-03-17 LIJIAJUN 先做一次本地词库的扫描替换，在正式纠错的时候就不要使用LOCAL纠错了
            sourceText = this.correctionDictService.localWordPlace(sourceText);
            log.info("源文本3：{}", sourceText);
            log.info("文本纠错前结果：{},{}", task.getSentence(), sourceText);
            // 查询任务ID
            String correctionText = correctService.correction(sourceText, correctConfig, taskId);
            log.info("【{}】文本纠错后结果：{}", correctConfig.getCode(), correctionText);
            String correctionTextV2 = "";
            if (StringUtils.hasText(correctionText)) {
                correctionTextV2 = this.correctionDictService.sensitiveWordPlace(correctionText, true);
            }
            boolean isPlaceWord = !correctionTextV2.equals(correctionText);
            if (isPlaceWord) {
                correctionText = correctionTextV2;
            }
            String category = null;
            String level = null;
            String source = null;
            if (correctConfig.getCode().equals(CorrectionModel.LOCAL)) {
                // 去除 ----- 及其后面的所有字符
                String beforeDash = CorrectUtils.removeAfterDash(correctionText);
                level = "一级";
                // 获取 ----- 后面的字符串
                localDictIds.addAll(CorrectUtils.getAfterDash(correctionText));
                correctionText = beforeDash;
            } else {
                if (correctionText != null) {
                    // TODO 2025-02-19 lijiajun 取出 category 和 source 暂时只有AI模型进行了返回
                    // 按照'----'分割字符串
                    List<String> cList = Splitter.on("----").splitToList(correctionText);
                    correctionText = getElementAtIndex(cList, 0);
                    category = getElementAtIndex(cList, 1);
                    level = getElementAtIndex(cList, 2);
                    source = getElementAtIndex(cList, 3);
                    // 如果进行了替换字符串，那么则认为是一级
                    if (isPlaceWord) {
                        level = "一级";
                    }
                    log.info("correctionText:{},category:{},level:{},source:{}", correctionText, category, level, source);
                }
            }
            // 纠错匹配
            // 如果 correctionText 包含 <br/> 则替换为 ""
//            if (null != correctionText) {
//                correctionText = correctionText.replaceAll("<br/>", "");
//            }

            log.info("纠错文本：{}", correctionText);
            List<TextCorrectionMatchResp> textCorrectionMatchRespList = TextCorrectMatch.obscureCompareTextsV2(correctConfig, task.getSentence(), correctionText, category, source, level);
            log.info("textCorrectionMatchRespList:{}", JSON.toJSONString(textCorrectionMatchRespList));
            if (!CollectionUtils.isEmpty(textCorrectionMatchRespList)) {
                correctResults.add(textCorrectionMatchRespList);
            }
        });
        log.info("localDictIds:{}", localDictIds);
        if (CollectionUtils.isEmpty(localDictIds)) {
            localDictIds.add(-1L);
        }
        Map<CorrectionModel, Integer> modelPriority = new HashMap<>();
        configList.forEach(config -> {
            modelPriority.put(config.getCode(), config.getOrder());
        });
        // 获取所有的本地词典
        List<CorrectionDict> correctionDictList = this.correctionDictService.listByIds(localDictIds);
        List<TextCorrectionMatchResp> diffList = new ArrayList<>();
        AtomicInteger localModelCorrectCount = new AtomicInteger();
        log.info("correctResults:{}", JSON.toJSONString(correctResults));
        correctResults.forEach(results -> {
            results.forEach(textCorrectionMatchResp -> {
                boolean isExist = false;
                // 判断每种模型的解析结果是否重复，并检查是否需要替换
                for (int i = 0; i < diffList.size(); i++) {
                    TextCorrectionMatchResp diff = diffList.get(i);
                    if (diff.getErrorStartIndex() == textCorrectionMatchResp.getErrorStartIndex() && diff.getErrorEndIndex() == textCorrectionMatchResp.getErrorEndIndex() && diff.getErrorText().equals(textCorrectionMatchResp.getErrorText())) {
                        // 判断模型优先级，如果优先级大于，则进行替换
                        if (modelPriority.getOrDefault(diff.getModelSource(), Integer.MAX_VALUE) > modelPriority.getOrDefault(textCorrectionMatchResp.getModelSource(), Integer.MAX_VALUE)) {
                            // 替换旧的结果
                            diffList.set(i, textCorrectionMatchResp);
                            // 如果是本地词典匹配，那么则需要进行匹配写入链接来源
                            if (textCorrectionMatchResp.getModelSource().equals(CorrectionModel.LOCAL)) {
                                if (localModelCorrectCount.get() < localDictIds.size()) {
                                    Long dictId = localDictIds.get(localModelCorrectCount.get());
                                    for (CorrectionDict dict : correctionDictList) {
                                        if (dict.getId().equals(dictId)) {
                                            textCorrectionMatchResp.setLinkSource(dict.getSource());
                                            break;
                                        }
                                    }
                                    localModelCorrectCount.incrementAndGet();
                                }
                            }
                        }
                        isExist = true;
                        break;
                    }
                }
                // 如果之前没有进行写入结果集，那么则进行写入，并且需要进行判断，如果是本地词典匹配，那么则需要进行匹配写入链接来源
                if (!isExist) {
                    if (textCorrectionMatchResp.getModelSource().equals(CorrectionModel.LOCAL)) {
                        if (localModelCorrectCount.get() < localDictIds.size()) {
                            Long i = localDictIds.get(localModelCorrectCount.get());
                            for (CorrectionDict dict : correctionDictList) {
                                if (dict.getId().equals(i)) {
                                    textCorrectionMatchResp.setLinkSource(dict.getSource());
                                }
                            }
                        }
                        localModelCorrectCount.getAndIncrement();
                    }
                    diffList.add(textCorrectionMatchResp);
                }
            });
        });

        // 准确差异位置
        List<TextCorrectionMatchResp> newResult = new ArrayList<>();
        for (TextCorrectionMatchResp r : diffList) {
            // TODO lijiajun 2025-02-19 字符串差异比较 diff
            newResult.add(diffInline(r));
        }
        // TODO 好像因为并发问题导致结果集有些问题，这个地方手动处理下，后面在排查把
//        List<TextCorrectionMatchResp> list = new ArrayList<>();
//        for (TextCorrectionMatchResp textCorrectionMatchResp : newResult) {
//            if (!textCorrectionMatchResp.getCorrectText().equals(textCorrectionMatchResp.getErrorText())
//                    && !textCorrectionMatchResp.getCorrectText().contains("<br/>")
//                    && !textCorrectionMatchResp.getErrorText().contains("<br/>")) {
//                list.add(textCorrectionMatchResp);
//            }
//        }
        // 将结果写入数据库
        task.setResult(newResult);
        this.correctTaskDetailsService.updateById(task);
    }


    TextCorrectTask findByTaskId(String taskId) {
        TextCorrectTask task = this.textCorrectTaskMapper.selectById(taskId);
        if (ObjectUtils.isEmpty(task)) {
            throw new BusinessException("任务不存在");
        }
        return task;
    }

    // 提取错误文本
    public List<String> extractErrorText(String text) {
        // 定义正则表达式，匹配 <error-text :...> 中的内容
        String regex = "<error-text\\s*:\\s*([^>]+)>";
        // 创建 Pattern 对象
        Pattern pattern = Pattern.compile(regex);
        // 创建 Matcher 对象
        Matcher matcher = pattern.matcher(text);
        // 用于存储提取结果的列表
        List<String> results = new ArrayList<>();
        // 查找所有匹配的内容
        while (matcher.find()) {
            // 提取第一个捕获组中的内容（即 : 后面的部分）
            String result = matcher.group(1).trim(); // 去掉多余空格
            results.add(result);
        }
        return results;
    }

    public CorrectTaskResp getCorrectTask(String taskId) {
        // 判断任务是否存在
        TextCorrectTask task = this.findByTaskId(taskId);
        // 获取任务解析详情 success 状态的
        List<CorrectTaskDetails> taskDetailsList = this.correctTaskDetailsService.findByTaskIdAndState(taskId, CorrectState.SUCCESS);

        // 查询一下连续的句子
        List<CorrectTaskDetails> list = new ArrayList<>();
        for (int i = 0; i < taskDetailsList.size(); i++) {
            CorrectTaskDetails taskDetails = taskDetailsList.get(i);
            if (taskDetails.getSort() != i + 1) {
                break;
            }
            // 需要判断一下，纠错结果集是否为空
            if (!CollectionUtils.isEmpty(taskDetails.getResult())) {
                list.add(taskDetails);
            }
        }
        List<CorrectTaskDetails> taskDetailsListV2 = new ArrayList<>();
        // 只取出三级的错误
        for (CorrectTaskDetails taskDetails : taskDetailsList) {
            List<TextCorrectionMatchResp> result = taskDetails.getResult();
            List<TextCorrectionMatchResp> resultV2 = new ArrayList<>();
            for (TextCorrectionMatchResp textCorrectionMatchResp : result) {
                if (!textCorrectionMatchResp.getLevel().equals("三级")
                        && textCorrectionMatchResp.getCorrectText().contains("</error-text>")
                        && textCorrectionMatchResp.getCorrectText().contains("<error-text")) {
                    // 如果有两个连续的 </error-text> 直接跳过
                    if (textCorrectionMatchResp.getCorrectText().contains("</error-text></error-text>")) {
                        continue;
                    }
                    List<String> errorTextList = this.extractErrorText(textCorrectionMatchResp.getCorrectText());
                    if (CollectionUtils.isEmpty(errorTextList)) {
                        continue;
                    }
                    boolean isExist = true;
                    for (String t : errorTextList) {
                        // 判断错误文本是否在原错误文本中
                        if (!textCorrectionMatchResp.getErrorText().contains(t)) {
                            isExist = false;
                            break;
                        }
                    }
                    if (isExist) {
                        resultV2.add(textCorrectionMatchResp);
                    }
                }
            }
            if (!CollectionUtils.isEmpty(resultV2)) {
                taskDetails.setResult(resultV2);
                taskDetailsListV2.add(taskDetails);
            }
        }

        log.info("连续句子:{}", JSON.toJSONString(list));
        List<CorrectTaskDetailsResp> details = SmartPageUtil.convert(taskDetailsListV2, CorrectTaskDetailsResp.class);
        details.forEach(detail -> {
            List<TextCorrectionMatchResp> result = detail.getResult();
            if (CollectionUtils.isEmpty(result)) {
                return;
            }
            log.info("newResult:{}", JSON.toJSONString(result));
            if (result.size() > 1) {
                // 排序
                result.sort(Comparator.comparingInt(TextCorrectionMatchResp::getErrorStartIndex));
            }
            // 2025-02-19 赋值比较字符串差异后的数据
            detail.setResult(result);
        });
        CorrectTaskResp resp = SmartPageUtil.convert(task, CorrectTaskResp.class);
        resp.setCorrectResult(details);
        // 获取当前已经完成了多少条数据了
        resp.setFinishCount(this.correctTaskDetailsService.countByFinishedAndTaskId(taskId));
        return resp;
    }

    TextCorrectionMatchResp diffInline(TextCorrectionMatchResp r) {
        // 使用谷歌diff插件进行字符串差异比较
        Patch<String> diff = DiffUtils.diffInline(r.getErrorText(), r.getCorrectText());
        List<AbstractDelta<String>> deltas = diff.getDeltas();
        if (CollectionUtils.isEmpty(deltas)) {
            return r;
        }
        for (AbstractDelta<String> delta : deltas) {
            // 错误源
            Chunk<String> source = delta.getSource();
            // 更改目标
            Chunk<String> target = delta.getTarget();
            // 如果源和目标都为空，则跳过
            if (CollectionUtils.isEmpty(source.getLines()) && CollectionUtils.isEmpty(target.getLines())) {
                continue;
            }
            // 赋值关键位置/字符信息
            r.setErrorChar(CollectionUtils.isEmpty(source.getLines()) ? "" : source.getLines().get(0));
            r.setErrorCharPosition(source.getPosition());
            r.setCorrectChar(CollectionUtils.isEmpty(target.getLines()) ? "" : target.getLines().get(0));
            r.setCorrectCharPosition(target.getPosition());
        }
        return r;
    }

    public static String getElementAtIndex(List<String> list, int index) {
        if (index >= 0 && index < list.size()) {
            return list.get(index);
        } else {
            return null;
        }
    }


//    public static void main(String[] args) {
//        String text = "“满足《网络安全》、《数据安全》、三级等保， 支持登录限制、支持国产接。”你号呀！是的。哈哈；“aaa?”";
//        List<CorrectUtils.TextSegment> segments = CorrectUtils.punctuateSplitTextV2(text);
//        for (CorrectUtils.TextSegment segment : segments) {
//            System.out.println(segment.getText());
//        }
//    }
}
